import Axios from './core/Axios'
import { extend } from './helpers/util'
import { AxiosStatic, AxiosRequestConfig } from './types'
import defaults from './defaults'
import mergeConfig from './core/mergeConfig'
import CancelToken from './cancel/CancelToken'
import Cancel, { isCancel } from './cancel/Cancel'

function createInstance(config: AxiosRequestConfig): AxiosStatic {
  const context = new Axios(config)
  // 这里的操作很牛逼（注意interceptors是一个对象）
  const instance = Axios.prototype.request.bind(context)

  // 注意这里的操作，instance下面的defaults属性和interceptors属性都是context对象中的引用，所以instance中的修改会影响context的修改
  extend(instance, context)

  return instance as AxiosStatic
}

// 注意这里是一个单例
// 由于import会进行缓存，所以只在第一次引入的时候执行本模块内容，后续引入都是取缓存（也就是对应的引用）
// 详情参考 https://www.yuque.com/docs/share/896dc2fb-b59a-485e-bf32-30c8c3c0a857?# 《深入浅出 Commonjs 和 Es Module》
const axios = createInstance(defaults)

// 注意通过 axios.defaults.baseURL 设置了之后会影响到新创建实例的 baseURL
// axios.defaults.baseURL = 'https://www.baidu.com'
// const instance = axios.create()
// instance.get('/foo')
// 最终请求的 url 地址为 https://www.baidu.com/foo
// 因为 defaults 是一个引用类型！！
axios.create = function(config) {
  return createInstance(mergeConfig(defaults, config))
}

axios.CancelToken = CancelToken
axios.Cancel = Cancel
axios.isCancel = isCancel

axios.all = function(promises) {
  return Promise.all(promises)
}

axios.spread = function(callback) {
  return function(arr) {
    return callback.apply(null, arr)
  }
}

axios.Axios = Axios

export default axios
